// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: donggu

#pragma once
#include <memory>
#include <string>
#include <vector>

#include "coin2/exchange/base/market/market_exchange_api.h"
#include "coin2/exchange/base/symbology/product.h"
#include "coin2/exchange/symbology.pb.h"

// ICurrency create_currency_from_str(
//   market_type, exchange, api_version, current_timestamp, symbol);
// IProduct create_product_from_str(
//   market_type, exchange, api_version, current_timestamp, symbol);

namespace impl {

using coin2::exchange::base::market::ExchangeType;
using coin2::exchange::base::market::MarketType;
using coin2::exchange::base::symbology::IProduct;
using coin2::exchange::symbology::ProductConfig;
using coin2::exchange::symbology::ProductRequest;

std::unique_ptr<IProduct> CreateProductFromNativeString(
    const MarketExchangeApi& mea,
    const std::string& symbol,
    int64_t resolve_timestamp,
    bool die_on_failure = true);

std::unique_ptr<IProduct> CreateProductFromNativeStringNoThrow(
    const MarketExchangeApi& mea,
    const std::string& symbol,
    int64_t resolve_timestamp);

// std::unique_ptr<IProduct> CreateProductFromAbsoluteNorm(
//     const MarketType& market,
//     const ExchangeType& exchange,
//     const std::string& symbol);
std::unique_ptr<IProduct> CreateProductFromNormString(
    MarketType market,
    ExchangeType exchange,
    const std::string& symbol,
    int64_t resolve_timestamp,
    bool die_on_failure = true);

std::unique_ptr<IProduct> CreateProductFromNormStringNoThrow(
    MarketType market,
    ExchangeType exchange,
    const std::string& symbol,
    int64_t resolve_timestamp);

// convenience function to remove api_version. delete later
std::unique_ptr<IProduct> CreateProductFromNormString(
    const MarketExchangeApi& mea,
    const std::string& symbol,
    int64_t resolve_timestamp,
    bool die_on_failure = true);

std::unique_ptr<IProduct> CreateProductFromUniqueString(
    const std::string& symbol,
    int64_t resolve_timestamp);

std::vector<std::unique_ptr<IProduct>> ProductRequestsFromConfig(
    const std::string& mea,
    const ProductConfig& config,
    int64_t timestamp = GetCurrentTimestamp(),
    bool die_on_failure = true);

std::unique_ptr<IProduct> ResolveProductRequest(
    const ProductRequest& req,
    int64_t resolve_timestamp,
    bool die_on_failure = true);

std::vector<std::unique_ptr<IProduct>> ResolveProductRequestFromPotentiallyWildcard(
    const ProductRequest& req,
    int64_t resolve_timestamp,
    bool die_on_failure = true);

std::vector<std::unique_ptr<IProduct>> FilterProductWithInSymbolGroups(
    const MarketExchangeApi& mea,
    std::vector<std::unique_ptr<IProduct>>& pre_products);
}  // namespace impl

// using impl::CreateProductFromAbsoluteNorm;
using impl::CreateProductFromNativeString;
using impl::CreateProductFromNativeStringNoThrow;
using impl::CreateProductFromNormString;
using impl::CreateProductFromNormStringNoThrow;
using impl::CreateProductFromUniqueString;
using impl::ProductRequestsFromConfig;
using impl::ResolveProductRequest;
using impl::ResolveProductRequestFromPotentiallyWildcard;
using impl::FilterProductWithInSymbolGroups;
